function [forc,forecast]=fmodel(model,KFStru,forecast,sampleStru)
% =========================================================================
% =========================================================================
% fmodel
%
% Generate model-based forecasts. 
% Code is used both for the constrainted and unconstrained model
%
% function [forc,forecast]=fmodel(model,KFStru,forecast,sampleStru)
%
%% 1. Inputs
% model                         : Contains solution matrices of model
% KFStru.smoothSt               : Last data state
% forecast.forecast.N           : Number of Forecasts
% forecast.constants            : Non-adjusted constant

%% 2. Outputs
% forc.rawForc:         [length(names.states)    NFORC] Matrix of forecasts
% forc.observeForc      [NZ                      NFORC] Matrix of forecasts
% forc.adjustedForc     forecasts with necessary adjustments
% forc.adjustedData     historical data with necessary adjustments
% =========================================================================
% =========================================================================
%% Generate Forecasts
% KFStru.smoothSt(end,:) is untransformed final state, in deviations from
% model mean Number of actual forecasts is NFORC-1, first entry is data.
numStates=length(KFStru.smoothSt(end,:));
forc.rawForc=zeros(numStates,forecast.N);
forc.observeForc =zeros(size(model.ZZ(:,:,end),1),forecast.N);
forc.rawForc(:,1)=KFStru.smoothSt(end,:)';
forc.observeForc( :,1)=model.ZZ(:,:,end)*(model.CC(:,end)+forc.rawForc(:,1) );

for ii=2:forecast.N;
    forc.rawForc(:,ii)=model.GG(:,:,end)*forc.rawForc(:,ii-1);
    forc.observeForc(:, ii)=model.ZZ(:,:,end)*(model.CC(:,end)+forc.rawForc(:,ii) );
end
forc.rawForc=forc.rawForc';
forc.observeForc =forc.observeForc' ;

%% Transform forecasts
nser=length(forecast.position);
forc.adjustedForc = zeros(forecast.N,nser);
for ii = 1:nser
    forc.adjustedForc(:,ii) = forc.rawForc(:,forecast.position(ii)) + forecast.constants(ii);
end

forc.adjustedData = zeros(length(sampleStru.cell),nser);
for ii=1:nser;
    forc.adjustedData(:,ii) = (KFStru.smoothSt(:,forecast.position(ii))+forecast.constants(ii) );
end
end



